home *** CD-ROM | disk | FTP | other *** search
/ Aminet 37 / Aminet 37 (2000)(Schatztruhe)[!][Jun 2000].iso / Aminet / dev / lang / sofa.lha / sofa / smalleiffel / sys / gc_lib / generic.c < prev    next >
Text File  |  2000-03-25  |  5KB  |  101 lines

  1. /*
  2. -- This file is  free  software, which  comes  along  with  SmallEiffel. This
  3. -- software  is  distributed  in the hope that it will be useful, but WITHOUT 
  4. -- ANY  WARRANTY;  without  even  the  implied warranty of MERCHANTABILITY or
  5. -- FITNESS  FOR A PARTICULAR PURPOSE. You can modify it as you want, provided
  6. -- this header is kept unaltered, and a notification of the changes is added.
  7. -- You  are  allowed  to  redistribute  it and sell it, alone or as a part of 
  8. -- another product.
  9. --          Copyright (C) 1994-98 LORIA - UHP - CRIN - INRIA - FRANCE
  10. --            Dominique COLNET and Suzanne COLLIN - colnet@loria.fr 
  11. --                       http://www.loria.fr/SmallEiffel
  12. --
  13. */
  14. /* 
  15.  
  16.    Files of directory SmallEiffel/gc_lib/ are supposed to define the 
  17.    appropriate `mark_stack_and_registers' C function which is called by the 
  18.    Garbage Collector (GC) of SmallEiffel. The `mark_stack_and_registers' 
  19.    function may changed from one system to another, but also from one C
  20.    compiler to another. On some architecture, addresses increase as the 
  21.    stack grows; or, conversely, addresses decrease as the stack grows.
  22.    A C compiler may be clever enough to hide some root object inside 
  23.    registers. Unfortunately all registers are not always accessible via 
  24.    the C `setjmp' function !
  25.  
  26.    Thus, in order to be able to use the GC on your architecture/C-compiler,
  27.    you have to provide the correct `mark_stack_and_registers' function.
  28.    
  29.    What is the `mark_stack_and_registers' function supposed to do ? 
  30.    The `mark_stack_and_registers' function is supposed to notify the GC 
  31.    with all possible root one can find in C stack and registers by calling
  32.    the `gc_mark' function. A root is an object which must not be collected.
  33.    The SmallEiffel GC already knows about some root objects like once 
  34.    function results or manifest strings. The `mark_stack_and_registers'
  35.    function have to notify others possible roots. Obviously, one can find
  36.    in the C stack any kind of adresses, but the `gc_mark' function is clever 
  37.    enough to determine if the passed pointer is an Eiffel object or not.
  38.    When the passed pointer reach some Eiffel object, this object as well as
  39.    its descendant(s) are automatically marked as un-collectable.
  40.  
  41.    In order to provide the most appropriate `mark_stack_and_registers' 
  42.    function, the very first question is to know about the way the C stack
  43.    is managed (addresses of the stack may increase or decrease as the C 
  44.    stack grows). In this "generic.c" file, the test is done dynamically
  45.    each time the `mark_stack_and_registers' is called. Indeed, the global
  46.    C variable `stack_bottom' is set with some pointer which is supposed to 
  47.    be the bottom of the stack (this variable is automatically initialized 
  48.    in the C main function). Using the current stack pointer inside 
  49.    `mark_stack_and_registers', it is quite obvious to determine if addresses 
  50.    increase or not as the C stack grows.
  51.    
  52.    The second problem to solve is to be sure that the bottom of the stack
  53.    is really reached. The global variable 'stack_bottom' is not always
  54.    accurately set. If it is the case, we have to go under the predefined
  55.    value of 'stack_bottom' on some architectures.
  56.    
  57.    Some roots may be stored only in registers and not in the C stack.
  58.    In order to reach registers as well, the first attempt is to use 
  59.    setjmp, in the hope that setjmp will save registers in the stack !
  60.    
  61.    Finally, I am not sure to that previous explaination are cler enough, 
  62.    be here is the "generic.c" definition of `mark_stack_and_registers'.
  63. */
  64.  
  65. void mark_stack_and_registers(void) {
  66.   /* 
  67.      Works on many architecture/C-compilers.
  68.   */
  69.   void**stack_pointer; /* Use to traverse the stack and registers assuming 
  70.               that `setjmp' will save registers in the C stack.
  71.                */
  72.   jmp_buf stack_top; /* The jmp_buf buffer is in the C stack. */
  73.  
  74.   (void)setjmp(stack_top); /* To fill the C stack with registers. */
  75.  
  76.   stack_pointer=((void**)(&stack_top)); 
  77.  
  78.   if (stack_pointer > stack_bottom){
  79.     /* 
  80.        Addresses increase as the stack grows (add some printf here to see
  81.        if this is true on your architecture).
  82.     */
  83.     stack_pointer+=(sizeof(jmp_buf)/sizeof(void*)); /* To traverse the
  84.                                jmp_buf as well.
  85.                             */
  86.     for ( ; stack_pointer >= stack_bottom; stack_pointer--) {
  87.       gc_mark(*stack_pointer);
  88.     }
  89.   }
  90.   else {
  91.     /*
  92.       Addresses decrease as the stack grows (add some printf here to see
  93.       if this is true on your architecture).
  94.     */
  95.     for ( ; stack_pointer <= stack_bottom; stack_pointer++) {
  96.       gc_mark(*stack_pointer);
  97.     }
  98.   }
  99. }
  100.  
  101.